package CelestialDataAccess;

import java.util.UUID;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import javax.sql.rowset.*; //provides cached row set interface
import java.sql.*;

public class Order implements IKey<UUID>{

    private UUID m_uidOrderID;
    private UUID m_uidTransactionID;
    private int m_iCustomerID;
    private int m_iEmployeeID;
    private Date m_dtOrderDate;
    private Date m_dtDispatchDate;
    private int m_iStatus;
    private String m_strRemarks;

    private Address m_addrBilling;
    private Address m_addrShipping;

    private List<OrderItem> m_lstOrderItems = new ArrayList<OrderItem>();

    private static IFactory<Order> m_factory = new IFactory<Order>(){

        public Order createT(CachedRowSet crs){

            Order order;
            OrderItem item;
            try{
                if(!crs.last()) return null;

                order = new Order();
                order.m_uidOrderID = UUID.fromString(crs.getString("OrderID"));
                order.m_uidTransactionID = UUID.fromString(crs.getString("TransactionID"));
                order.m_dtDispatchDate = crs.getDate("DispatchDate");
                order.m_dtOrderDate = crs.getDate("OrderDate");
                order.m_iCustomerID = crs.getInt("CustomerID");
                order.m_iEmployeeID = crs.getInt("EmployeeID");
                order.m_iStatus = crs.getInt("Status");
                order.m_strRemarks = crs.getString("Remarks");

                Address addrBilling = new Address();
                addrBilling.Country = crs.getString("BillingCountry");
                addrBilling.City = crs.getString("BillingCity");
                addrBilling.State = crs.getString("BillingState");
                addrBilling.AddressLine1 = crs.getString("BillingAddressLine1");
                addrBilling.AddressLine2 = crs.getString("BillingAddressLine2");
                addrBilling.PostalCode = crs.getString("BillingPostalCode");

                Address addrShipping= new Address();
                addrShipping.Country = crs.getString("ShippingCountry");
                addrShipping.City = crs.getString("ShippingCity");
                addrShipping.State = crs.getString("ShippingState");
                addrShipping.AddressLine1 = crs.getString("ShippingAddressLine1");
                addrShipping.AddressLine2 = crs.getString("ShippingAddressLine2");
                addrShipping.PostalCode = crs.getString("ShippingPostalCode");

                /* populate order items */
                crs.absolute(-1);
                while(crs.next()){
                    item = new OrderItem();
                    item.m_bPriceOverride = crs.getBoolean("PriceOverride");
                    item.m_dblUnitPrice  =crs.getDouble("UnitPrice");
                    item.m_iQuantity = crs.getInt("Quantity");
                    item.m_strProductID = crs.getString("ProductID");
                    item.m_uidOrderItemID = order.m_uidOrderID;

                    order.addItem(item);
                }
            }catch(SQLException ex){
                return null;
            }
            return order;
        }
    };
    /*************************************************************************/
    /* get and set methods */
    public UUID getOrderID(){ return m_uidOrderID;};
    /*-----------------------------------------------------------------------*/
    public UUID getTransactionID(){ return m_uidTransactionID;}
    public void setTransactionID(UUID trans_id){ m_uidTransactionID = trans_id;}
    /*-----------------------------------------------------------------------*/
    public int getCustomerID(){ return m_iCustomerID;}
    public void setCustomerID(int cust_id){ m_iCustomerID = cust_id;}
    /*-----------------------------------------------------------------------*/
    public int getEmployeeID(){ return m_iEmployeeID;}
    public void setEmployeeID(int emp_id){ m_iEmployeeID = emp_id;}
    /*-----------------------------------------------------------------------*/
    public Date getOrderDate(){ return m_dtOrderDate;}
    public void setOrderDate(Date order_date){ m_dtOrderDate = order_date;}
    /*-----------------------------------------------------------------------*/
    public Date getDispatchDate(){ return m_dtDispatchDate;}
    public void setDispatchDate(Date order_date){ m_dtDispatchDate = order_date;}
    /*-----------------------------------------------------------------------*/
    public int getStatus(){ return m_iStatus;}
    public void setStatus(int status){ m_iStatus = status;}
    /*-----------------------------------------------------------------------*/
    public String getRemarks(){ return m_strRemarks;}
    public void setRemarks(String remarks){m_strRemarks = remarks;}
    /*-----------------------------------------------------------------------*/
    public Address getBillingAddress(){ return m_addrBilling;}
    public void setBillingAddress(Address addr){ m_addrBilling = addr;}
    /*-----------------------------------------------------------------------*/
    public Address getShippingAddress(){ return m_addrShipping;}
    public void setShippingAddress(Address addr){ m_addrShipping = addr;}
    /*-----------------------------------------------------------------------*/
    public double getTotalAmount(){

        double total = 0.0;
        for(OrderItem item : m_lstOrderItems)
            total += item.m_iQuantity * item.m_dblUnitPrice;
        return total;
    }
    /*-----------------------------------------------------------------------*/
    public Collection<OrderItem> getOrderItems(){ return Collections.unmodifiableCollection(m_lstOrderItems); }
    /*************************************************************************/
    /* Constructors */
    public Order(){
        m_uidOrderID = UUID.randomUUID();
        m_uidTransactionID = UUID.randomUUID();
    }
    /*-----------------------------------------------------------------------*/
    static Order createOrder(CachedRowSet crs){
        return m_factory.createT(crs);
    }
    /*************************************************************************/
    /* Client methods */
    public void clearItems(){ m_lstOrderItems.clear(); }
    /*-----------------------------------------------------------------------*/
    public boolean containsItem(Product prod){

        for(OrderItem item: m_lstOrderItems)
            if(item.m_strProductID.compareTo(prod.getProductID())==0)
                return true;
        return false;
    }
    /*-----------------------------------------------------------------------*/
    public int indexOf(Product prod){

        for(int i=0 ; i < m_lstOrderItems.size(); i++)
            if(m_lstOrderItems.get(i).m_strProductID.compareTo(prod.getProductID())==0)
                return i;
        return -1;
    }
    /*-----------------------------------------------------------------------*/
    public void addItem(Product prod, int qty){

        /* see if it exists */
        if(containsItem(prod))
            m_lstOrderItems.get(m_lstOrderItems.indexOf(prod)).m_iQuantity += qty;
        else
            m_lstOrderItems.add(new OrderItem(prod, qty));
    }
    /*-----------------------------------------------------------------------*/
    public void addItem(OrderItem item){ m_lstOrderItems.add(item);}
    /*-----------------------------------------------------------------------*/
    public void removeItem(Product prod){
  
        int i = indexOf(prod);
        if(i > 0) m_lstOrderItems.remove(i);
    }
    /*************************************************************************/
     //<editor-fold defaultstate="collapsed" desc="interfaces">
    /* IKey */
    public UUID getKey(){ return m_uidOrderID; }
    /*************************************************************************/
    /* IComparable */
    public int compareTo(Object order){
        return this.m_uidOrderID.compareTo(((Order)order).m_uidOrderID);
    } //</editor-fold>
}
